// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

using Hybrid.Extensions;

using IdentityModel;

using IdentityServer4;
using IdentityServer4.Configuration;
using IdentityServer4.Extensions;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using IdentityServer4.Stores.Serialization;

using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;

using System;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Threading.Tasks;

using static IdentityModel.OidcConstants;

namespace Hybrid.Zero.IdentityServer4
{
    /// <summary>
    /// Custom token creation service
    /// </summary>
    public class CustomTokenCreationService : ITokenCreationService
    {
        /// <summary>
        /// The PersistedGrantStore.
        /// </summary>
        protected readonly IPersistedGrantStore Store;

        /// <summary>
        /// The PersistentGrantSerializer;
        /// </summary>
        protected readonly IPersistentGrantSerializer Serializer;

        /// <summary>
        /// The key service
        /// </summary>
        protected readonly IKeyMaterialService Keys;

        /// <summary>
        /// The logger
        /// </summary>
        protected readonly ILogger Logger;

        /// <summary>
        ///  The clock
        /// </summary>
        protected readonly ISystemClock Clock;

        /// <summary>
        /// The options
        /// </summary>
        protected readonly IdentityServerOptions Options;

        /// <summary>
        /// Initializes a new instance of the <see cref="DefaultTokenCreationService"/> class.
        /// </summary>
        /// <param name="store">The store.</param>
        /// <param name="serializer">The serializer.</param>
        /// <param name="clock">The options.</param>
        /// <param name="keys">The keys.</param>
        /// <param name="options">The options.</param>
        /// <param name="logger">The logger.</param>
        public CustomTokenCreationService(
            IPersistedGrantStore store,
            IPersistentGrantSerializer serializer,
            ISystemClock clock,
            IKeyMaterialService keys,
            IdentityServerOptions options,
            ILogger<DefaultTokenCreationService> logger)
        {
            Store = store;
            Serializer = serializer;
            Clock = clock;
            Keys = keys;
            Options = options;
            Logger = logger;
        }

        /// <summary>
        /// Creates the token.
        /// </summary>
        /// <param name="token">The token.</param>
        /// <returns>
        /// A protected and serialized security token
        /// </returns>
        public virtual async Task<string> CreateTokenAsync(Token token)
        {
            var header = await CreateHeaderAsync(token);
            var payload = await CreatePayloadAsync(token);
            return await CreateJwtAsync(new JwtSecurityToken(header, payload), token);
        }

        /// <summary>
        /// Creates the JWT header
        /// </summary>
        /// <param name="token">The token.</param>
        /// <returns>The JWT header</returns>
        protected virtual async Task<JwtHeader> CreateHeaderAsync(Token token)
        {
            //var credential = await Keys.GetSigningCredentialsAsync(token.AllowedSigningAlgorithms);
            var credential = await Keys.GetSigningCredentialsAsync();
            if (credential == null)
            {
                throw new InvalidOperationException("No signing credential is configured. Can't create JWT token");
            }

            var header = new JwtHeader(credential);

            // emit x5t claim for backwards compatibility with v4 of MS JWT library
            if (credential.Key is X509SecurityKey x509key)
            {
                var cert = x509key.Certificate;
                if (Clock.UtcNow.UtcDateTime > cert.NotAfter)
                {
                    Logger.LogWarning("Certificate {subjectName} has expired on {expiration}", cert.Subject, cert.NotAfter.ToString(CultureInfo.InvariantCulture));
                }

                header["x5t"] = Base64Url.Encode(cert.GetCertHash());
            }

            if (token.Type == TokenTypes.AccessToken)
            {
                if (Options.AccessTokenJwtType.IsPresent())
                {
                    header["typ"] = Options.AccessTokenJwtType;
                }
            }

            return header;
        }

        /// <summary>
        /// Creates the JWT payload
        /// </summary>
        /// <param name="token">The token.</param>
        /// <returns>The JWT payload</returns>
        protected virtual Task<JwtPayload> CreatePayloadAsync(Token token)
        {
            var payload = token.CreateJwtPayload(Clock, Logger);
            return Task.FromResult(payload);
        }

        /// <summary>
        /// Applies the signature to the JWT
        /// </summary>
        /// <param name="jwt">The JWT object.</param>
        /// <param name="token">The token.</param>
        /// <returns>The signed JWT</returns>
        protected virtual async Task<string> CreateJwtAsync(JwtSecurityToken jwt, Token token)
        {
            var handler = new JwtSecurityTokenHandler();
            string accessToken = handler.WriteToken(jwt);
            //return Task.FromResult(handler.WriteToken(jwt));
            await StoreItemAsync(accessToken, token, token.ClientId, token.SubjectId, token.CreationTime, token.Lifetime);
            return accessToken;
        }

        private const string KeySeparator = ":";

        //private const string GrantType = "jwt_token";
        private const string GrantType = IdentityServerConstants.PersistedGrantTypes.ReferenceToken;

        /// <summary>
        /// Gets the hashed key.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        protected virtual string GetHashedKey(string value)
        {
            return (value + KeySeparator + GrantType).Sha256();
        }

        /// <summary>
        /// Stores the item.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="item">The item.</param>
        /// <param name="clientId">The client identifier.</param>
        /// <param name="subjectId">The subject identifier.</param>
        /// <param name="created">The created.</param>
        /// <param name="lifetime">The lifetime.</param>
        /// <returns></returns>
        protected virtual Task StoreItemAsync(string key, Token item, string clientId, string subjectId, DateTime created, int lifetime)
        {
            return StoreItemAsync(key, item, clientId, subjectId, created, created.AddSeconds(lifetime));
        }

        /// <summary>
        /// Stores the item.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="item">The item.</param>
        /// <param name="clientId">The client identifier.</param>
        /// <param name="subjectId">The subject identifier.</param>
        /// <param name="created">The created.</param>
        /// <param name="expiration">The expiration.</param>
        /// <returns></returns>
        protected virtual async Task StoreItemAsync(string key, Token item, string clientId, string subjectId, DateTime created, DateTime? expiration)
        {
            key = GetHashedKey(key);

            var json = Serializer.Serialize(item);

            var grant = new PersistedGrant
            {
                Key = key,
                Type = GrantType,
                ClientId = clientId,
                SubjectId = subjectId,
                CreationTime = created,
                Expiration = expiration,
                Data = json
            };

            await Store.StoreAsync(grant);
        }
    }
}

///// <summary>
///// Default token service
///// </summary>
//public class CustomTokenService : ITokenService
//{
//    /// <summary>
//    /// The logger
//    /// </summary>
//    protected readonly ILogger Logger;

//    /// <summary>
//    /// The HTTP context accessor
//    /// </summary>
//    protected readonly IHttpContextAccessor Context;

//    /// <summary>
//    /// The claims provider
//    /// </summary>
//    protected readonly IClaimsService ClaimsProvider;

//    /// <summary>
//    /// The reference token store
//    /// </summary>
//    protected readonly IReferenceTokenStore ReferenceTokenStore;

//    /// <summary>
//    /// The signing service
//    /// </summary>
//    protected readonly ITokenCreationService CreationService;

//    /// <summary>
//    /// The clock
//    /// </summary>
//    protected readonly ISystemClock Clock;

//    /// <summary>
//    /// The key material service
//    /// </summary>
//    protected readonly IKeyMaterialService KeyMaterialService;

//    /// <summary>
//    /// The IdentityServer options
//    /// </summary>
//    protected readonly IdentityServerOptions Options;

//    /// <summary>
//    /// Initializes a new instance of the <see cref="DefaultTokenService" /> class.
//    /// </summary>
//    /// <param name="claimsProvider">The claims provider.</param>
//    /// <param name="referenceTokenStore">The reference token store.</param>
//    /// <param name="creationService">The signing service.</param>
//    /// <param name="contextAccessor">The HTTP context accessor.</param>
//    /// <param name="clock">The clock.</param>
//    /// <param name="keyMaterialService"></param>
//    /// <param name="options">The IdentityServer options</param>
//    /// <param name="logger">The logger.</param>
//    public CustomTokenService(
//        IClaimsService claimsProvider,
//        IReferenceTokenStore referenceTokenStore,
//        ITokenCreationService creationService,
//        IHttpContextAccessor contextAccessor,
//        ISystemClock clock,
//        IKeyMaterialService keyMaterialService,
//        IdentityServerOptions options,
//        ILogger<DefaultTokenService> logger)
//    {
//        Context = contextAccessor;
//        ClaimsProvider = claimsProvider;
//        ReferenceTokenStore = referenceTokenStore;
//        CreationService = creationService;
//        Clock = clock;
//        KeyMaterialService = keyMaterialService;
//        Options = options;
//        Logger = logger;
//    }

//    /// <summary>
//    /// Creates an identity token.
//    /// </summary>
//    /// <param name="request">The token creation request.</param>
//    /// <returns>
//    /// An identity token
//    /// </returns>
//    public virtual async Task<Token> CreateIdentityTokenAsync(TokenCreationRequest request)
//    {
//        Logger.LogTrace("Creating identity token");
//        request.Validate();

//        var credential = await KeyMaterialService.GetSigningCredentialsAsync();
//        if (credential == null)
//        {
//            throw new InvalidOperationException("No signing credential is configured.");
//        }

//        var signingAlgorithm = credential.Algorithm;

//        // host provided claims
//        var claims = new List<Claim>();

//        // if nonce was sent, must be mirrored in id token
//        if (request.Nonce.IsPresent())
//        {
//            claims.Add(new Claim(JwtClaimTypes.Nonce, request.Nonce));
//        }

//        // add iat claim
//        claims.Add(new Claim(JwtClaimTypes.IssuedAt, Clock.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64));

//        // add at_hash claim
//        if (request.AccessTokenToHash.IsPresent())
//        {
//            claims.Add(new Claim(JwtClaimTypes.AccessTokenHash, CryptoHelper.CreateHashClaimValue(request.AccessTokenToHash, signingAlgorithm)));
//        }

//        // add c_hash claim
//        if (request.AuthorizationCodeToHash.IsPresent())
//        {
//            claims.Add(new Claim(JwtClaimTypes.AuthorizationCodeHash, CryptoHelper.CreateHashClaimValue(request.AuthorizationCodeToHash, signingAlgorithm)));
//        }

//        // add s_hash claim
//        if (request.StateHash.IsPresent())
//        {
//            // todo: need constant
//            claims.Add(new Claim(JwtClaimTypes.StateHash, request.StateHash));
//        }

//        // add sid if present
//        if (request.ValidatedRequest.SessionId.IsPresent())
//        {
//            claims.Add(new Claim(JwtClaimTypes.SessionId, request.ValidatedRequest.SessionId));
//        }

//        claims.AddRange(await ClaimsProvider.GetIdentityTokenClaimsAsync(
//            request.Subject,
//            request.Resources,
//            request.IncludeAllIdentityClaims,
//            request.ValidatedRequest));

//        var issuer = Context.HttpContext.GetIdentityServerIssuerUri();

//        var token = new Token(OidcConstants.TokenTypes.IdentityToken)
//        {
//            CreationTime = Clock.UtcNow.UtcDateTime,
//            Audiences = { request.ValidatedRequest.Client.ClientId },
//            Issuer = issuer,
//            Lifetime = request.ValidatedRequest.Client.IdentityTokenLifetime,
//            Claims = claims.Distinct(new ClaimComparer()).ToList(),
//            ClientId = request.ValidatedRequest.Client.ClientId,
//            AccessTokenType = request.ValidatedRequest.AccessTokenType
//        };

//        return token;
//    }

//    /// <summary>
//    /// Creates an access token.
//    /// </summary>
//    /// <param name="request">The token creation request.</param>
//    /// <returns>
//    /// An access token
//    /// </returns>
//    public virtual async Task<Token> CreateAccessTokenAsync(TokenCreationRequest request)
//    {
//        Logger.LogTrace("Creating access token");
//        request.Validate();

//        var claims = new List<Claim>();
//        claims.AddRange(await ClaimsProvider.GetAccessTokenClaimsAsync(
//            request.Subject,
//            request.Resources,
//            request.ValidatedRequest));

//        if (request.ValidatedRequest.Client.IncludeJwtId)
//        {
//            claims.Add(new Claim(JwtClaimTypes.JwtId, CryptoRandom.CreateUniqueId(16)));
//        }

//        var issuer = Context.HttpContext.GetIdentityServerIssuerUri();
//        var token = new Token(OidcConstants.TokenTypes.AccessToken)
//        {
//            CreationTime = Clock.UtcNow.UtcDateTime,
//            Issuer = issuer,
//            Lifetime = request.ValidatedRequest.AccessTokenLifetime,
//            Claims = claims.Distinct(new ClaimComparer()).ToList(),
//            ClientId = request.ValidatedRequest.Client.ClientId,
//            AccessTokenType = request.ValidatedRequest.AccessTokenType
//        };

//        if (Options.EmitLegacyResourceAudienceClaim)
//        {
//            token.Audiences.Add(string.Format(IdentityServerConstants.AccessTokenAudience, issuer.EnsureTrailingSlash()));
//        }

//        foreach (var api in request.Resources.ApiResources)
//        {
//            if (api.Name.IsPresent())
//            {
//                token.Audiences.Add(api.Name);
//            }
//        }

//        return token;
//    }

//    /// <summary>
//    /// Creates a serialized and protected security token.
//    /// </summary>
//    /// <param name="token">The token.</param>
//    /// <returns>
//    /// A security token in serialized form
//    /// </returns>
//    /// <exception cref="System.InvalidOperationException">Invalid token type.</exception>
//    public virtual async Task<string> CreateSecurityTokenAsync(Token token)
//    {
//        string tokenResult;

//        if (token.Type == OidcConstants.TokenTypes.AccessToken)
//        {
//            if (token.AccessTokenType == AccessTokenType.Jwt)
//            {
//                Logger.LogTrace("Creating JWT access token");

//                tokenResult = await CreationService.CreateTokenAsync(token);
//            }
//            else
//            {
//                Logger.LogTrace("Creating reference access token");

//                var handle = await ReferenceTokenStore.StoreReferenceTokenAsync(token);

//                tokenResult = handle;
//            }
//        }
//        else if (token.Type == OidcConstants.TokenTypes.IdentityToken)
//        {
//            Logger.LogTrace("Creating JWT identity token");

//            tokenResult = await CreationService.CreateTokenAsync(token);
//        }
//        else
//        {
//            throw new InvalidOperationException("Invalid token type.");
//        }

//        return tokenResult;
//    }
//}

//// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
//// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

//using Hybrid.Extensions;
//using IdentityModel;
//using IdentityServer4;
//using IdentityServer4.Configuration;
//using IdentityServer4.Extensions;
//using IdentityServer4.Models;
//using IdentityServer4.Services;
//using IdentityServer4.Stores;
//using Microsoft.AspNetCore.Authentication;
//using Microsoft.AspNetCore.Http;
//using Microsoft.Extensions.Logging;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Security.Claims;
//using System.Threading.Tasks;

//namespace Hybrid.Zero.IdentityServer4
//{
//    /// <summary>
//    /// Default token service
//    /// </summary>
//    public class CustomTokenService : ITokenService
//    {
//        /// <summary>
//        /// The logger
//        /// </summary>
//        protected readonly ILogger Logger;

//        /// <summary>
//        /// The HTTP context accessor
//        /// </summary>
//        protected readonly IHttpContextAccessor ContextAccessor;

//        /// <summary>
//        /// The claims provider
//        /// </summary>
//        protected readonly IClaimsService ClaimsProvider;

//        /// <summary>
//        /// The reference token store
//        /// </summary>
//        protected readonly IReferenceTokenStore ReferenceTokenStore;

//        /// <summary>
//        /// The signing service
//        /// </summary>
//        protected readonly ITokenCreationService CreationService;

//        /// <summary>
//        /// The clock
//        /// </summary>
//        protected readonly ISystemClock Clock;

//        /// <summary>
//        /// The key material service
//        /// </summary>
//        protected readonly IKeyMaterialService KeyMaterialService;

//        /// <summary>
//        /// The IdentityServer options
//        /// </summary>
//        protected readonly IdentityServerOptions Options;

//        /// <summary>
//        /// Initializes a new instance of the <see cref="DefaultTokenService" /> class.
//        /// </summary>
//        /// <param name="claimsProvider">The claims provider.</param>
//        /// <param name="referenceTokenStore">The reference token store.</param>
//        /// <param name="creationService">The signing service.</param>
//        /// <param name="contextAccessor">The HTTP context accessor.</param>
//        /// <param name="clock">The clock.</param>
//        /// <param name="keyMaterialService"></param>
//        /// <param name="options">The IdentityServer options</param>
//        /// <param name="logger">The logger.</param>
//        public CustomTokenService(
//            IClaimsService claimsProvider,
//            IReferenceTokenStore referenceTokenStore,
//            ITokenCreationService creationService,
//            IHttpContextAccessor contextAccessor,
//            ISystemClock clock,
//            IKeyMaterialService keyMaterialService,
//            IdentityServerOptions options,
//            ILogger<DefaultTokenService> logger)
//        {
//            ContextAccessor = contextAccessor;
//            ClaimsProvider = claimsProvider;
//            ReferenceTokenStore = referenceTokenStore;
//            CreationService = creationService;
//            Clock = clock;
//            KeyMaterialService = keyMaterialService;
//            Options = options;
//            Logger = logger;
//        }

//        /// <summary>
//        /// Creates an identity token.
//        /// </summary>
//        /// <param name="request">The token creation request.</param>
//        /// <returns>
//        /// An identity token
//        /// </returns>
//        public virtual async Task<Token> CreateIdentityTokenAsync(TokenCreationRequest request)
//        {
//            Logger.LogTrace("Creating identity token");
//            request.Validate();

//            // todo: Dom, add a test for this. validate the at and c hashes are correct for the id_token when the client's alg doesn't match the server default.
//            var credential = await KeyMaterialService.GetSigningCredentialsAsync(request.ValidatedRequest.Client.AllowedIdentityTokenSigningAlgorithms);
//            if (credential == null)
//            {
//                throw new InvalidOperationException("No signing credential is configured.");
//            }

//            var signingAlgorithm = credential.Algorithm;

//            // host provided claims
//            var claims = new List<Claim>();

//            // if nonce was sent, must be mirrored in id token
//            if (request.Nonce.IsPresent())
//            {
//                claims.Add(new Claim(JwtClaimTypes.Nonce, request.Nonce));
//            }

//            // add iat claim
//            claims.Add(new Claim(JwtClaimTypes.IssuedAt, Clock.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64));

//            // add at_hash claim
//            if (request.AccessTokenToHash.IsPresent())
//            {
//                claims.Add(new Claim(JwtClaimTypes.AccessTokenHash, CryptoHelper.CreateHashClaimValue(request.AccessTokenToHash, signingAlgorithm)));
//            }

//            // add c_hash claim
//            if (request.AuthorizationCodeToHash.IsPresent())
//            {
//                claims.Add(new Claim(JwtClaimTypes.AuthorizationCodeHash, CryptoHelper.CreateHashClaimValue(request.AuthorizationCodeToHash, signingAlgorithm)));
//            }

//            // add s_hash claim
//            if (request.StateHash.IsPresent())
//            {
//                claims.Add(new Claim(JwtClaimTypes.StateHash, request.StateHash));
//            }

//            // add sid if present
//            if (request.ValidatedRequest.SessionId.IsPresent())
//            {
//                claims.Add(new Claim(JwtClaimTypes.SessionId, request.ValidatedRequest.SessionId));
//            }

//            claims.AddRange(await ClaimsProvider.GetIdentityTokenClaimsAsync(
//                request.Subject,
//                request.Resources,
//                request.IncludeAllIdentityClaims,
//                request.ValidatedRequest));

//            var issuer = ContextAccessor.HttpContext.GetIdentityServerIssuerUri();

//            var token = new Token(OidcConstants.TokenTypes.IdentityToken)
//            {
//                CreationTime = Clock.UtcNow.UtcDateTime,
//                Audiences = { request.ValidatedRequest.Client.ClientId },
//                Issuer = issuer,
//                Lifetime = request.ValidatedRequest.Client.IdentityTokenLifetime,
//                Claims = claims.Distinct(new ClaimComparer()).ToList(),
//                ClientId = request.ValidatedRequest.Client.ClientId,
//                AccessTokenType = request.ValidatedRequest.AccessTokenType,
//                AllowedSigningAlgorithms = request.ValidatedRequest.Client.AllowedIdentityTokenSigningAlgorithms
//            };

//            return token;
//        }

//        /// <summary>
//        /// Creates an access token.
//        /// </summary>
//        /// <param name="request">The token creation request.</param>
//        /// <returns>
//        /// An access token
//        /// </returns>
//        public virtual async Task<Token> CreateAccessTokenAsync(TokenCreationRequest request)
//        {
//            Logger.LogTrace("Creating access token");
//            request.Validate();

//            var claims = new List<Claim>();
//            claims.AddRange(await ClaimsProvider.GetAccessTokenClaimsAsync(
//                request.Subject,
//                request.Resources,
//                request.ValidatedRequest));

//            if (request.ValidatedRequest.Client.IncludeJwtId)
//            {
//                claims.Add(new Claim(JwtClaimTypes.JwtId, CryptoRandom.CreateUniqueId(16)));
//            }

//            var issuer = ContextAccessor.HttpContext.GetIdentityServerIssuerUri();
//            var token = new Token(OidcConstants.TokenTypes.AccessToken)
//            {
//                CreationTime = Clock.UtcNow.UtcDateTime,
//                Issuer = issuer,
//                Lifetime = request.ValidatedRequest.AccessTokenLifetime,
//                Claims = claims.Distinct(new ClaimComparer()).ToList(),
//                ClientId = request.ValidatedRequest.Client.ClientId,
//                AccessTokenType = request.ValidatedRequest.AccessTokenType,
//                AllowedSigningAlgorithms = request.Resources.ApiResources.FindMatchingSigningAlgorithms()
//            };

//            if (Options.EmitLegacyResourceAudienceClaim)
//            {
//                token.Audiences.Add(string.Format(IdentityServerConstants.AccessTokenAudience, issuer.EnsureTrailingSlash()));
//            }

//            // add cnf if present
//            if (request.ValidatedRequest.Confirmation.IsPresent())
//            {
//                token.Confirmation = request.ValidatedRequest.Confirmation;
//            }
//            else
//            {
//                if (Options.MutualTls.AlwaysEmitConfirmationClaim)
//                {
//                    var clientCertificate = await ContextAccessor.HttpContext.Connection.GetClientCertificateAsync();
//                    if (clientCertificate != null)
//                    {
//                        token.Confirmation = clientCertificate.CreateThumbprintCnf();
//                    }
//                }
//            }

//            foreach (var api in request.Resources.ApiResources)
//            {
//                if (api.Name.IsPresent())
//                {
//                    token.Audiences.Add(api.Name);
//                }
//            }

//            return token;
//        }

//        /// <summary>
//        /// Creates a serialized and protected security token.
//        /// </summary>
//        /// <param name="token">The token.</param>
//        /// <returns>
//        /// A security token in serialized form
//        /// </returns>
//        /// <exception cref="System.InvalidOperationException">Invalid token type.</exception>
//        public virtual async Task<string> CreateSecurityTokenAsync(Token token)
//        {
//            string tokenResult;

//            if (token.Type == OidcConstants.TokenTypes.AccessToken)
//            {
//                if (token.AccessTokenType == AccessTokenType.Jwt)
//                {
//                    Logger.LogTrace("Creating JWT access token");

//                    tokenResult = await CreationService.CreateTokenAsync(token);
//                }
//                else
//                {
//                    Logger.LogTrace("Creating reference access token");

//                    var handle = await ReferenceTokenStore.StoreReferenceTokenAsync(token);

//                    tokenResult = handle;
//                }
//            }
//            else if (token.Type == OidcConstants.TokenTypes.IdentityToken)
//            {
//                Logger.LogTrace("Creating JWT identity token");

//                tokenResult = await CreationService.CreateTokenAsync(token);
//            }
//            else
//            {
//                throw new InvalidOperationException("Invalid token type.");
//            }

//            return tokenResult;
//        }
//    }
//}